// GLObject3D.h

#ifndef GLOBJECT3D_H_
#define GLOBJECT3D_H_

#define GL3_PROTOTYPES

// Include the vector and matrix utilities from the textbook, as well as some
// macro definitions.
#include "Angel.h"

#ifdef __APPLE__
#  include <OpenGL/gl3.h>
#endif

#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>

// APPARENTLY, I NEED A LATER Boost lib, so I'm commenting this out for now.
//#include <boost/uuid/uuid.hpp>
//#include <boost/uuid/uuid_generators.hpp>

#include <vector>
#include <map>
#include "DebugHelper.h"

using namespace std;

namespace Voltron
{



	class GLObject3D
	{

		private:

		// Private Constructors
		// Private Destructor
		// Private properties
		// Private members

		protected:

		// Protected Constructors
		// Protected Destructor
		// Protected properties
		// Protected members

		public:
		enum BufferType
		{
			POSITION=0,
			COLOR, //1
			NORMAL, //2
			FACE, //3
			TEXTURE //4
			// more here in the future
		};


		// Public Constructors
		GLObject3D();
		GLObject3D(int quantityVerts);
		GLObject3D(int quantityVerts, vec4* positionVerts, vec4* colorVerts, GLuint shaderprogram);
		GLObject3D(int quantityVerts, vec4* positionVerts, vec4* colorVerts,vec4 selectionColor, GLuint shaderprogram);

		// Public Destructor
		~GLObject3D();

		// Public properties

		// basic unique id for GLObjects.
		// This should probably exist deeper in the framework as
		// an ancestor to all indexable classes in the framework
		// then searching and cross referenceing by the UUID
		// would be trivial across different reference containers.

		// APPARENTLY, I NEED A LATER Boost lib, so I'm commenting this out for now.
		//boost::uuids::uuid _uuid;


		// OpenGL VAO
		// one VAO object
		GLuint	_vao[1];

		// OpenGL VBOs pointer
		// _vbo["position"] is typically for position verticies
		// _vbo["color"] is typically for color verticies
		//vector<GLuint>*	_vbo;
		//std::map<string, GLuint>* _vbo;
		//std::map<string, GLuint> _vbo;
		GLuint _vbo[5]; // index into these with BufferType enum

        //vector<vec4>*	_pointVerts;
        // format of positionVert is x,y,z,w as vec4(x,y,z,w)
        vector<vec4>	_positionVerts;

        // format of normal is x,y,z as vec4(x,y,z,0.0)
        vector<vec4>	_normals;

        // format of color vert is RGBA, as vec4(R,B,G,A)
        vector<vec4>	_colorVerts;

        // faces are a set of indexes into
        // the position, texture, and normal verticies
        // is v/vt/vn as vec3(v,vt,vn)
        vector<vector<vec3> >	_faces;

        vector<vec4>	_textures;

        vector<vec4>	_rawPositionVerts;
        vector<vec4>	_rawNormals;

        vec4            _selectionColor;

        GLint           flag;
        GLuint          SelectFlagLoc;
        GLuint          selectionColorR, selectionColorG, selectionColorB, selectionColorA;
        GLuint          SelectColorRLoc, SelectColorGLoc, SelectColorBLoc, SelectColorALoc;

        string _objectFilename;
        uint _quantityVerts;
        uint _quantityFaces;
        mat4 _model;

		// Public members
		void attachVertexPositionShader(GLuint shaderprogram);
		void attachVertexColorShader(GLuint shaderprogram);
		void attachNormalShader(GLuint shaderprogram);
		void initBuffers();
		void initBuffers(GLuint shaderprogram);
		void initSelectionColor(GLuint shaderprogram);
		void syncSelectionColor();
		void makeActiveObject();
		uint getbyteBufferSize();

		void loadGLObjectFromFile();
		void loadGLObjectFromFile(string filename);

		virtual void render();
                virtual void renderSelectionColor();
                virtual bool isSelected(GLubyte pixel[4]);
                virtual void setDrawMode(GLenum mode);

                virtual mat4 transformModel(mat4 transform);
	};
}

#endif
